home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir35
/
cff51b.zip
/
PORTS
/
CFPORT.EMX
< prev
next >
Wrap
Text File
|
1993-10-22
|
16KB
|
780 lines
/* CFPORT.EMX */
/* PORTABILITY FOR CFF -- MODIFY TO SUIT THE COMPILER/OS IN USE */
#define INCL_BASE
#define INCL_DOSMEMMGR
#include <os2.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <io.h>
#include <share.h>
#include <stdio.h>
#include <dirent.h>
#include <dos.h>
#include "..\cff.h"
extern void *mymemmove(void *, void *, long);
#define PCDOS 0 /* EMX CRASHES WHEN _int86 is used with -ac. Why?? */
#ifndef HAS_NO_SBRK
#define HAS_NO_SBRK 0
#endif
#define NIBBLE 128
#define CHUNK_SIZE 8192
#ifndef HEAPSTART
#define HEAPSTART 0x02100000
#endif
int heapcreep;
void *heapstart = (void *)HEAPSTART;
static STOR BIGZERO;
/* DUMMY ROUTINES TO PREVENT LINKING UNWANTED MALLOC LIKE STUFF */
int _heapchk(void)
{
return 0;
}
int _heapset(unsigned a)
{
return 0;
}
void *_expand (void *mem, size_t new_size)
{
return NULL;
}
size_t _msize (const void *mem)
{
return mallocsize(mem);
}
/* ----------------- END OF MALLOC DUMMYS -------------------- */
static __inline__ unsigned long
round_up(long size, long amt)
{
return (size&(amt-1)) ? size+(amt-(size&(amt-1))) : size;
}
static int testflags = 0;
void
cfport_settestflags(int flags)
{
testflags |= flags;
}
void
cfport_clrtestflags(int flags)
{
testflags &= ~flags;
}
static void
fix_statbuf(struct stat *stat, CFSTAT *sbuf)
{
sbuf->st_atime = stat->st_atime;
sbuf->st_mtime = stat->st_mtime;
sbuf->st_ctime = stat->st_ctime;
sbuf->st_size = stat->st_size;
sbuf->st_alloc = stat->st_size;
sbuf->st_filesize = stat->st_size;
sbuf->st_filealloc = stat->st_size;
#if 0
sbuf->st_blksize = stat->st_blksize;
#else
sbuf->st_blksize = 8192;
#endif
sbuf->st_dev = stat->st_dev;
sbuf->st_ino = stat->st_ino;
sbuf->st_nlink = stat->st_nlink;
sbuf->st_uid = stat->st_uid;
sbuf->st_gid = stat->st_gid;
sbuf->st_rdev = stat->st_rdev;
sbuf->st_mode = stat->st_mode;
}
#if HAS_NO_SBRK == 1
static int sbrk_initted = 0;
void *sbrkmem_base = NULL;
static unsigned long mem_alloced = 0;
static unsigned long sbrk_alloced = 0;
static int
get_os2_memory(void)
{
void *my_base;
unsigned long my_alloced;
/* Allocate 32 Megabytes of uncommitted memory -- this is the OS2 limit */
my_alloced = 32*1024*1024;
while(DosAllocMem(&my_base, my_alloced, PAG_READ|PAG_WRITE))
{/* Failure -- try smaller allocation */
if(my_alloced <= 4*1024*1024)
return 0;
my_alloced -= 4*1024*1024;
}
/* Check coalesce */
if(my_base == ((char *)sbrkmem_base + mem_alloced))
mem_alloced += my_alloced;
else
{
sbrkmem_base = my_base;
mem_alloced = my_alloced;
sbrk_alloced = 0;
}
return 1;
}
void *sbrk(int amount)
{
int commit = 1;
if(!sbrk_initted)
{
if(!get_os2_memory())
abort();
sbrk_initted = 1;
}
/*
OS2 Memory management is utterly terrible and stupid, memory should be
committed only when it is ACCESSED for the first time, and even then
it should not be allocated to pages in the swap file until swapping
of a particular page is required.
*/
if(amount < 0)
{
amount = -amount;
commit = 0;
}
for(;;)
{
if((amount + sbrk_alloced) <= mem_alloced)
{
void *return_base = (char *)sbrkmem_base + sbrk_alloced;
sbrk_alloced += amount;
if(commit)
DosSetMem(return_base, amount, PAG_COMMIT|PAG_READ|PAG_WRITE);
return return_base;
}
if(!get_os2_memory())
return ((void *)-1);
}
}
#endif
void *
PORTSBRK(unsigned long amt)
{
return sbrk(amt);
}
void
PORTHEAPSTART(void)
{
void *curstart = sbrk(0);
char *nextstart = NULL;
unsigned long zone;
if(curstart > heapstart)
{
cfprintf("CFPORT: The heap safety zone was exceeded by %d bytes.\n",
-((long)(heapstart - curstart)));
cfprintf(" Modify 'heapstart' in cfport.c\n");
#if HAS_NO_SBRK == 1
cfprintf(" sbrkmem_base=0x%lx=%lu sbrk_alloc=%lu\n",
sbrkmem_base, sbrkmem_base, mem_alloced);
#endif
exit(-1);
}
zone = heapcreep = (unsigned long)(heapstart - curstart);
while(zone != 0)
{
int amount;
char *newstart;
if(zone > 1024*1024)
amount = 1024*1024;
else amount = zone;
#if HAS_NO_SBRK == 1
newstart = sbrk(-amount); /* Don't commit the memory */
#else
newstart = sbrk(amount);
#endif
if(newstart == (void *)-1) {
cfprintf("Failed to set heap: zone=%lu HSTART=%p cstart=%p left=%lu.\n",
heapcreep, heapstart, curstart, zone);
exit(-2);
}
zone -= amount;
nextstart = newstart + amount;
}
if(heapcreep && nextstart != heapstart) {
cfprintf("Heap was not set properly: desired=%p result=%p zone=%lu\n",
heapstart, nextstart, heapcreep);
exit(-3);
}
}
int
PORTSTAT(void *path, CFSTAT *sbuf)
{
struct stat _stat;
int result = stat(path, &_stat);
if(result == 0)
fix_statbuf(&_stat, sbuf);
return result;
}
void
PORTFSTAT(int handle, CFSTAT *sbuf)
{
struct stat stat;
fstat(handle, &stat);
fix_statbuf(&stat, sbuf);
}
long
PORTREAD(long handle, void *mem_addr, STOR dsk_addr, long amount)
{
lseek(handle, dsk_addr.a0, SEEK_SET);
return read(handle, mem_addr, amount);
}
long
PORTWRITE(long handle, void *mem_addr, STOR dsk_addr, long amount)
{
lseek(handle, dsk_addr.a0, SEEK_SET);
return write(handle, mem_addr, amount);
}
void
PORTSEEK(long handle, STOR spot, int mode, STOR *loc)
{
STOR ret;
switch(mode)
{
case S_END:
mode = SEEK_END;
break;
case S_CUR:
mode = SEEK_CUR;
break;
case S_SET:
mode = SEEK_SET;
break;
default:
mode = -1;
}
ret.a4.s1 = 0;
ret.a4.s0 = lseek((int)handle, spot.a0, mode);
if(loc)
*loc = ret;
}
long
PORTOPEN(void *path, int mode)
{
int omode = O_BINARY;
if(mode & F_STAT)
omode |= O_RDONLY;
else if((mode & F_RDWR) == F_RDWR)
omode |= O_RDWR;
else if((mode & F_RDWR) == F_WRONLY)
omode |= O_RDWR;
else if((mode & F_RDWR) == F_RDONLY)
omode |= O_RDONLY;
if(mode & F_TRUNC)
omode |= O_TRUNC;
if(mode & F_EXCL)
omode |= O_EXCL;
if(mode & F_APPEND)
omode |= O_APPEND;
return open(path,omode);
}
long
PORTCLOSE(long handle)
{
return close((int)handle);
}
long
PORTCREATE(void *path, int mode)
{
int shflg;
if(mode & F_EXCL)
shflg = SH_DENYRW;
else shflg = SH_DENYNO;
return sopen(path,O_BINARY|O_CREAT|O_TRUNC|O_RDWR,shflg,S_IREAD|S_IWRITE);
}
long
PORTUNLINK(void *path)
{
return unlink(path);
}
#if PCDOS == 1
static void
dos_truncate(short handle, long amount)
{
#include <dos.h>
union REGS r;
r.h.al = 0; /* SEEK_SET */
r.h.ah = 0x42; /* seek */
r.x.bx = handle;
r.x.dx = (short)amount;
r.x.cx = (short)(amount>>16);
_int86(0x21,&r,&r);
r.h.ah = 0x40; /* write */
r.x.bx = handle;
r.x.cx = 0; /* amount == 0 */
_int86(0x21,&r,&r);
r.h.ah = 0x3e; /* close */
r.x.bx = handle;
_int86(0x21,&r,&r);
}
#endif
long
PORTTRUNCATE(long handle, char *path, STOR amount)
{
#if PCDOS == 1
if(_emx_env & 0x200)
{/* Running under OS2 */
ftruncate((int)handle, amount.a0);
return handle;
}
else
{/* This isnt necessary, EMX can truncate a a DOS file, DJCC cannot. */
dos_truncate((short)handle, amount.a0);
return PORTOPEN(path, F_RDWR);
}
#else
ftruncate((int)handle, amount.a0);
return handle;
#endif
}
void
PORTCLOSETRUNC(long handle, STOR amount)
{
#if PCDOS == 1
if(_emx_env & 0x200)
{/* Running under OS2 */
ftruncate((int)handle, amount.a0);
close ((int)handle);
}
else
dos_truncate((short)handle, amount.a0);
#else
ftruncate((int)handle, amount.a0);
close((int)handle);
#endif
}
static __inline__ void
sync(void)
{/* EMX doesn't know about sync */
}
void
PORTFLUSH(long handle)
{
if(handle < 0)
sync();
else fsync((int)handle);
}
char *
PORTGETCWD(void *buf, int maxlen)
{
char *result;
result = getcwd((char *)buf, maxlen);
((char *)buf)[maxlen] = 0;
if(result)
{
while(*((char *)buf))
{
if(*((char *)buf) == '\\') *((char *)buf) = '/';
++((char *)buf);
}
}
return result;
}
long
PORTCHDIR(void *path)
{
return chdir(path);
}
unsigned long
PORTTIME(void)
{
return time(NULL);
}
unsigned long
PORTCLOCK(void)
{
return clock();
}
volatile void
PORTABORT(void)
{
extern volatile void abort();
abort();
}
/* THE BASIC OS DRIVERS */
/* Primary Memory driver */
long
pmem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
switch(func)
{
case S_GETSPACE:
{
unsigned long min, nib, current;
amount = round_up(amount, CHUNK_SIZE);
min = round_up(amount / 4, CHUNK_SIZE);
nib = round_up(amount / 16, CHUNK_SIZE);
current = amount;
((STOR *)mem_addr)->a2.size = 0;
((STOR *)mem_addr)->a2.type = STO_CHUNK;
while(current >= min) {
if((((STOR *)mem_addr)->a1 = PORTSBRK(current)) != (void *)-1) {
if(((STOR *)mem_addr)->a0 & (NIBBLE-1))
{/* Normally the system uses NIBBLE bytes as the alignment */
((STOR *)mem_addr)->a0 =
round_up(((STOR *)mem_addr)->a0, NIBBLE);
current -= NIBBLE;
}
((STOR *)mem_addr)->a2.size = current;
return 0;
}
current -= nib;
}
return 1;
}
case S_GIVESPACE:
return 1;
default:
return 1;
}
return 0;
}
/* Secondary Memory driver */
long
smem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
if(!(testflags & 1))
{/*
IF SECONDARY MEMORY REALLY EXISTS, THEN PUT A REAL DRIVER HERE.
The system adapts to a 0 return from S_GETSPACE by mapping
secondary memory to primary memory when cfinit is called.
S_OPEN is never called.
*/
switch (func)
{
case S_GETSPACE:
*((long *)mem_addr) = 0;
break;
}
return -1;
} /* END: Real driver */
else {
/* THIS CODE IS JUST FOR TESTING PURPOSES, IT USES A LOCAL MEMORY BUFFER */
#define SMEMMAX (4096*1024)
static char *sbuf = NULL;
static long smemalloc = 0;
if(sbuf == NULL) {
if((sbuf = PORTSBRK(SMEMMAX)) == (void *)-1) {
cfprintf("SMEM_DRIVER: Failed to init test memory block.\n");
exit(-1);
}
}
switch(func)
{
case S_CLOSE:
return 0; /* a real driver would do something */
case S_READBLK:
case S_WRITEBLK:
{
char *smemaddr = sbuf + dsk_addr.a0;
long xfer = amount;
if(dsk_addr.a0 + amount > smemalloc)
xfer = smemalloc - dsk_addr.a0;
if(xfer < 0) {
return -1;
}
if(func == S_READBLK)
mymemmove(mem_addr, smemaddr, xfer);
else mymemmove(smemaddr, mem_addr, xfer);
return xfer;
}
case S_GETSPACE:
amount = round_up(amount, CHUNK_SIZE);
((STOR *)mem_addr)->a0 = smemalloc;
((STOR *)mem_addr)->a2.size = 0;
((STOR *)mem_addr)->a2.type = STO_CHUNK;
if(amount + smemalloc < SMEMMAX) {
((STOR *)mem_addr)->a2.size = amount;
smemalloc += amount;
return 0;
} else {/* Not enough space available, return error + avail */
((STOR *)mem_addr)->a2.size =
(SMEMMAX - smemalloc) & ~CHUNK_SIZE;
return 1;
}
case S_GIVESPACE:
#if 0
cfprintf("SMEM: GIVESPACE at loc=%lx size=%lu curbase=%lx\n",
((STOR *)mem_addr)->a0, ((STOR *)mem_addr)->a2.size, smemalloc);
#endif
if(((STOR *)mem_addr)->a0 ==
smemalloc - ((STOR *)mem_addr)->a2.size)
{/* Accept returns if they are at the end */
smemalloc -= ((STOR *)mem_addr)->a2.size;
#if 0
cfprintf("SMEM: Truncate to %lu bytes\n", smemalloc);
#endif
return 0;
}
break;
default:
break;
}
return 1;
}/* END: test driver */
}
/* Internal file driver */
long
cfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
long result = 0;
switch(func)
{
case S_READBLK:
result = PORTREAD(handle, mem_addr, dsk_addr, amount);
break;
case S_WRITEBLK:
result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
break;
case S_GETSPACE:
{
unsigned long result;
STOR base;
STOR end;
PORTSEEK(handle, BIGZERO, S_END, &base);
amount = round_up(amount, CHUNK_SIZE);
end.a4.s0 = base.a0 + amount-1;
end.a4.s1 = 0;
PORTWRITE(handle, "0", end, 1);
PORTSEEK(handle, BIGZERO, S_END, &end);
result = end.a0 - base.a0;
((STOR *)mem_addr)->a0 = base.a0;
((STOR *)mem_addr)->a2.size = result;
((STOR *)mem_addr)->a2.type = STO_CHUNK;
return (result == amount) ? 0:1;
}
case S_GIVESPACE:
{
STOR base;
PORTSEEK(handle, BIGZERO, S_END, &base);
if((((STOR *)mem_addr)->a0 + ((STOR *)mem_addr)->a2.size) == base.a0)
{/* OK to return space if at end */
#if 0
long result;
base.a0 -= ((STOR *)mem_addr)->a2.size;
result = PORTTRUNCATE(handle, base);
#endif
return 0;
}
else return 1;
}
case S_OPEN:
result = PORTOPEN(mem_addr, handle);
break;
case S_CLOSE:
result = PORTCLOSE(handle);
break;
case S_CREATE:
result = PORTCREATE(mem_addr, handle);
break;
case S_UNLINK:
result = PORTUNLINK(mem_addr);
break;
case S_SEEK:
PORTSEEK(handle, dsk_addr, amount, mem_addr);
break;
case S_FLUSH:
PORTFLUSH(handle);
break;
case S_CLOSETRUNC: /* truncate and close, (PCDOS needs this) */
PORTCLOSETRUNC(handle, dsk_addr);
break;
default:
return 1;
}
return result;
}
/* External file driver */
long
xfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
{
long result = 0;
switch(func)
{
case S_GETSPACE:
((STOR *)mem_addr)->a2.size = 0;
case S_GIVESPACE:
return 1;
case S_OPEN:
result = PORTOPEN(mem_addr, handle);
break;
case S_CLOSE:
result = PORTCLOSE(handle);
break;
case S_UNLINK:
result = PORTUNLINK(mem_addr);
break;
case S_CREATE:
result = PORTCREATE(mem_addr,handle);
break;
case S_READBLK:
result = PORTREAD(handle, mem_addr, dsk_addr, amount);
break;
case S_WRITEBLK:
result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
break;
case S_SEEK:
PORTSEEK(handle, dsk_addr, amount, mem_addr);
break;
case S_FLUSH:
PORTFLUSH(handle);
break;
default:
return 1;
}
return result;
}
void *
PORTOPENDIR(char *name)
{
return opendir(name);
}
void *
PORTREADDIR(void *it, CFDIRENT *d)
{
struct dirent *rd;
if((rd = readdir(it))) {
d->d_namlen = rd->d_namlen;
d->d_name = rd->d_name;
d->d_mode = M_EXTRNFILE;
}
return rd;
}
void
PORTTELLDIR(void *it, STOR *loc)
{
STOR me;
me.item = 0;
me.a0 = telldir(it);
if(loc)
*loc = me;
}
void
PORTSEEKDIR(void *it, STOR *loc)
{
seekdir(it, loc->a0);
}
void
PORTREWINDDIR(void *it)
{
rewinddir(it);
}
long
PORTCLOSEDIR(void *it)
{
return closedir(it);
}
int
PORTPRINT(int c)
{
return write(1, &c, 1);
}
#if 0
/*
THIS CODE IS FOR SAMPLE PURPOSES ONLY -- THE REAL CODE IS IN THE LIBRARY
PROGRAMMERS WHO WISH TO CREATE CUSTOM COMPARISON ROUTINES CAN USE THESE
FUNCTIONS AS MODELS.
*/
/*
default_keycmp - system key comparison
Return: LESS if keya < keyb
EQUAL if keya == keyb
GREATER if keya > keyb
*/
static __inline__ int
mymemcmp(unsigned char *a, unsigned char *b, int len)
{
int result = 0;
do {
if((result = ((int)*a++) - ((int)*b++)))
return result;
} while(--len);
return result;
}
int
default_keycmp (void *keya, int lena, void *keyb, int lenb)
{
int result;
if (lena == 0)
return ( (lenb == 0) ? EQUAL : LESS );
else if (lenb == 0)
return (GREATER);
result = mymemcmp (keya, keyb, ((lena<lenb)?lena:lenb));
if (result < 0)
return LESS;
if (result > 0)
return GREATER;
return ((lena == lenb) ? EQUAL : ((lena < lenb) ? LESS : GREATER));
}
/*
default_itemcmp - system item comparison
Return: LESS-1 if itema < itemb
EQUAL+1 if itema == itemb
GREATER+1 if itema > itemb
*/
int
default_itemcmp (Item *a, Item *b)
{
return ( (a->item == b->item) ?
EQUAL+1 : ((a->item < b->item) ? LESS-1 : GREATER+1) );
}
#endif